<template>
  <div>
    <input type="file" @change="handleFileChange" />
    <button @click="uploadFile">Upload</button>
  </div>
</template>

<script>
import md5 from 'md5'; // 使用 md5 库来生成文件的 md5

export default {
  data() {
    return {
      file: null,
      chunkSize: 1024 * 1024, // 切片大小为1MB
      uploadedChunks: new Set(),
      totalChunks: 0,
      concurrentUploads: 6,
    };
  },
  methods: {
    handleFileChange(event) {
      this.file = event.target.files[0];
      this.totalChunks = Math.ceil(this.file.size / this.chunkSize);
      this.uploadedChunks = new Set(); // 清空已上传的切片集合
      this.getUploadedChunks();
    },

    getUploadedChunks() {
      // 这里可以请求后端返回已上传的切片
      // 假设后端返回一个数组 [0, 1] 表示已上传切片
      fetch('/api/uploaded-chunks?md5=' + md5(this.file))
        .then(response => response.json())
        .then(data => {
          data.forEach(chunk => this.uploadedChunks.add(chunk));
        });
    },

    async uploadFile() {
      const fileMD5 = md5(this.file);
      const promises = [];

      for (let i = 0; i < this.totalChunks; i++) {
        if (!this.uploadedChunks.has(i)) {
          const start = i * this.chunkSize;
          const end = Math.min(start + this.chunkSize, this.file.size);
          const chunk = this.file.slice(start, end);
          promises.push(this.uploadChunk(chunk, fileMD5, i));
        }
      }

      // 限制并发请求数
      while (promises.length) {
        await Promise.all(promises.splice(0, this.concurrentUploads));
      }

      // 所有切片上传完毕，合并切片
      await this.mergeChunks(fileMD5);
    },

    uploadChunk(chunk, md5, index) {
      const formData = new FormData();
      formData.append('file', chunk);
      formData.append('index', index);
      formData.append('md5', md5);

      return fetch('/api/upload', {
        method: 'POST',
        body: formData,
      });
    },

    mergeChunks(md5) {
      return fetch('/api/merge', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ md5, totalChunks: this.totalChunks }),
      });
    },
  },
};
</script>